package com.collect.senegal.zhiGlobal.zhiHandler;

import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Build;

import com.collect.senegal.zhiGlobal.zhiAppSettings.ZHIProjectConfigs;
import com.collect.senegal.zhiHelper.ZHIDeviceHelper;
import com.collect.senegal.zhiNetApi.ZHIHttpApiProvider;
import com.collect.senegal.zhiUtils.MyLogger;

import org.json.JSONObject;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.text.SimpleDateFormat;
import java.util.Date;

import okhttp3.Call;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;

public class ZHICrashHelper implements Thread.UncaughtExceptionHandler {

    private static final String TAG = "CFCrashHelper";

    private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");

    //系统默认的UncaughtException处理类
    private Thread.UncaughtExceptionHandler mUncaughtExceptionHandler;
    //CrashHandler实例
    private static ZHICrashHelper mZHICrashHelper = new ZHICrashHelper();
    //程序的Context对象
    private Context mContext;

    private ZHICrashHelper() {
    }

    public static ZHICrashHelper getInstance() {
        return mZHICrashHelper;
    }

    public void init(Context context) {
        mContext = context;
        //获取系统默认的UncaughtException处理器
        mUncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
        //设置该CrashHandler为程序的默认处理器
        Thread.setDefaultUncaughtExceptionHandler(this);
    }

    /**
     * 当UncaughtException发生时会转入该函数来处理
     *
     * @param thread 线程
     * @param ex     异常
     */
    @Override
    public void uncaughtException(Thread thread, Throwable ex) {
        catchException(ex);
        if (mUncaughtExceptionHandler != null) {
            //让系统默认的异常处理器来处理
            mUncaughtExceptionHandler.uncaughtException(thread, ex);
        } else {
            //退出程序
            //退出JVM(java虚拟机),释放所占内存资源,0表示正常退出(非0的都为异常退出)
            System.exit(0);
            //从操作系统中结束掉当前程序的进程
            android.os.Process.killProcess(android.os.Process.myPid());
        }

    }

    /**
     * 自定义错误处理,收集错误信息 发送错误报告等操作均在此完成.
     *
     * @param throwable 异常
     * @return true:如果处理了该异常信息;否则返回false.
     */
    private boolean catchException(final Throwable throwable) {
        if (throwable == null) {
            return false;
        }

        //收集设备参数信息
        try {
            String info = getCrashReleateInfo(throwable);
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("message", info);
            jsonObject.put("product", "DUN");
            jsonObject.put("androidId", ZHIDeviceHelper.getInstance().getAndroidID());

            String url = ZHIProjectConfigs.DEFAULT_URL + "/front/v1/appLog";
            reportInfo(url, jsonObject.toString());
        } catch (Exception e) {
            MyLogger.e(TAG, "异常异常 : " + e.toString());
        }

        return true;
    }

    /**
     * 收集设备信息
     *
     * @type method
     * @author liwenjie
     * @creatTime 2020-03-20 16:21
     */
    public String getCrashReleateInfo(Throwable ex) {

        StringBuilder info = new StringBuilder();
        try {
            PackageManager pm = mContext.getPackageManager();
            PackageInfo pi = pm.getPackageInfo(mContext.getPackageName(), PackageManager.GET_ACTIVITIES);
            if (pi != null) {
                String versionName = pi.versionName == null ? "unknown" : pi.versionName;
                String versionCode = pi.versionCode + "";
                info.append("应用版本:" + versionName + "," + versionCode);
                info.append('\n');
            }
        } catch (PackageManager.NameNotFoundException e) {
            MyLogger.e(TAG, "an error occured when collect package info" + e.toString());
        }
        info.append("型号:" + getDeviceModel());
        info.append('\n');
        info.append("系统:" + getOs());
        info.append('\n');
        info.append("设备标识:" + ZHIDeviceHelper.getInstance().getUDID());
        info.append('\n');
        info.append("A_ID:" + ZHIDeviceHelper.getInstance().getAndroidID());
        info.append('\n');

        SimpleDateFormat formatter = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");

        info.append("时间:" + formatter.format(new Date()));
        info.append('\n');

        Writer writer = new StringWriter();
        PrintWriter printWriter = new PrintWriter(writer);
        ex.printStackTrace(printWriter);
        Throwable cause = ex.getCause();
        while (cause != null) {
            cause.printStackTrace(printWriter);
            cause = cause.getCause();
        }
        printWriter.close();

        info.append("堆栈信息:");
        info.append(writer.toString());

        return info.toString();
    }

    public String getDeviceModel() {
        return Build.BRAND + "," + Build.MODEL;
    }

    public String getOs() {
        return "Android " + Build.VERSION.RELEASE;
    }

    //同步提交异常信息
    private void reportInfo(final String url, final String info) throws Exception {

        Thread thread =  new Thread(new Runnable(){
            @Override
            public void run() {
                OkHttpClient okHttpClient = ZHIHttpApiProvider.genericClient();
                RequestBody body = RequestBody.create(JSON, info);

                final Request request = new Request.Builder()
                        .url(url)
                        .post(body)
                        .build();
                Call call = okHttpClient.newCall(request);//3.使用client去请求
                try {
                    String result = call.execute().body().string();//4.获得返回结果
                    MyLogger.e(TAG,  result);
                } catch (Exception e) {
                    MyLogger.e(TAG,  "上传异常信息失败" +  e.toString());
                }
            }
        });
        thread.start();
        thread.join(15000);
    }

}